import { HttpStatus, Injectable } from '@nestjs/common';
import { CreateArticleDto } from './dto/create-article.dto';
import { UpdateArticleDto } from './dto/update-article.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { Article } from './entities/article.entity';
import { UserAccount } from 'src/user_account/entities/user_account.entity';
import { ArticleTag } from './entities/article_tags.entity';
import { ArticleComment } from './entities/comment.entity';
import { buildCommentTree } from './commentTree';

@Injectable()
export class ArticleService {

  constructor(@InjectRepository(Article) private readonly article: Repository<Article>,
    @InjectRepository(UserAccount) private readonly userAccount: Repository<UserAccount>,
    @InjectRepository(ArticleTag) private readonly articleTag: Repository<ArticleTag>,
    @InjectRepository(ArticleComment) private readonly articleComment: Repository<ArticleComment>,
  ) {

  }

  /** 
    **@description: 创建文章  
    **/
  async create(createArticleDto: CreateArticleDto) {
    const statusObj = { 0: '待审核', 1: '待发布', 2: '已发布', 3: '未通过', 4: '草稿箱', 5: '已删除' }
    const msgObj = { 0: '等待审核', 4: '已加入草稿箱' }
    try {
      const userAccount = await this.userAccount.findOne({ where: { uuid: createArticleDto.uuid }, relations: ['articles'] })
      if (!userAccount) return { code: HttpStatus.NOT_FOUND, msg: '未找到用户(uuid)' }
      const article = new Article()
      // //循环遍历对象的属性
      for (let key in createArticleDto) {
        key !== 'uuid' && key !== 'publish_status' && key !== 'tags' && (article[key] = createArticleDto[key])
      }
      article.publish_status = statusObj[createArticleDto.publish_status]
      let articleTags: Array<ArticleTag> = []
      //添加文章标签
      for (let i = 0; i < createArticleDto.tags.length; i++) {
        const articleTag = new ArticleTag()
        articleTag.name = createArticleDto.tags[i]
        await this.articleTag.save(articleTag)
        articleTags.push(articleTag)
      }
      article.tags = articleTags
      const data = await this.article.save(article)
      userAccount.articles.push(article)
      await this.userAccount.save(userAccount)
      return {
        code: HttpStatus.OK,
        msg: msgObj[createArticleDto.publish_status],
        data
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_GATEWAY,
        msg: '错误',
        data: error
      }
    }
  }
  /** 
     **@description: 条件匹配查询文章    
     **/
  async findArticles(query?: { uuid?: string, keyword?: string, publish_status?: number, right?: string, pageSize?: number, page?: number, limit?: number, orderDto?: { sort: string, order: "ASC" | "DESC" } }) {
    const { keyword, uuid, publish_status, right, pageSize, page, limit, orderDto } = query

    const queryBuilder = this.article.createQueryBuilder('article')
      .leftJoinAndSelect('article.userAccount', 'userAccount')
      .leftJoinAndSelect('article.tags', 'articleTag')
      .groupBy(`article.id`)
      .select(['article.id', 'article.title', 'article.category', 'article.publish_status', 'article.author', 'article.right', 'article.introduction', 'articleTag'])
    if (orderDto) {
      queryBuilder
        .leftJoinAndSelect(`article.${orderDto.sort}`, orderDto.sort)
        .orderBy(`COUNT(${orderDto.sort}.id)`, orderDto.order)
    } else {
      queryBuilder.orderBy('article.id', 'DESC')
    }
    if (pageSize && page) {
      queryBuilder.take(pageSize).skip((page - 1) * pageSize)
    }
    if (uuid) {
      queryBuilder.where('userAccount.uuid = :uuid', { uuid })
    }
    if (publish_status) {
      const statusObj = { 0: '待审核', 1: '待发布', 2: '已发布', 3: '未通过', 4: '草稿箱', 5: '已删除' }
      queryBuilder.andWhere('article.publish_status = :publish_status', { publish_status: statusObj[publish_status] })
    }
    if (keyword) {
      queryBuilder.andWhere('article.title LIKE :keyword OR articleTag.name LIKE :keyword OR article.category LIKE :keyword', { keyword: `%${keyword}%` })
      // queryBuilder.andWhere('MATCH(article.title) AGAINST (:keyword IN BOOLEAN MODE) OR  MATCH(articleTag.name) AGAINST (:keyword IN BOOLEAN MODE)', { keyword })
    }
    if (right) {
      queryBuilder.andWhere('article.right = :right', { right })
    }


    if (limit) {
      queryBuilder.limit(limit)
    }


    const articles = await queryBuilder.getMany()
    // console.log(articles,keyword);
    const total = await queryBuilder.getCount()

    if (articles) {
      return {
        code: HttpStatus.OK,
        msg: '查询成功',
        data: {
          articles,
          total,
          // xxx
        }
      }
    } else {
      return {
        code: HttpStatus.NOT_FOUND,
        msg: '查询失败'
      }
    }

  }


  //id查询某一篇文章
  async findOne(id: number, uuid: string) {
    try {
      const userAccount = await this.userAccount.findOne({ where: { uuid }, relations: ['views'] })
      const article = await this.article.findOne({ where: { id }, relations: ['viewer'] })
      const hasViewed = userAccount.views.findIndex(item => item.id === id)
      if (hasViewed === -1) {
        //没浏览过
        userAccount.views.push(article)
        await this.userAccount.save(userAccount)
      }

      const queryBuilder = this.article.createQueryBuilder('article')
        .leftJoinAndSelect('article.userAccount', 'userAccount')
        .leftJoinAndSelect('userAccount.follower', 'follower')
        // .leftJoinAndSelect('article.comment', 'comment')
        // .innerJoinAndSelect('comment.userAccount', 'author')
        // .innerJoinAndSelect('comment.replies','replies')
        // .innerJoinAndSelect('userAccount.follower','follower')
        // .innerJoinAndSelect('userAccount.followings', 'followings')
        .leftJoinAndSelect('article.beCollected', 'beCollected')
        .leftJoinAndSelect('article.liker', 'liker')
        .leftJoinAndSelect('article.viewer', 'viewer')
        .leftJoinAndSelect('article.tags', 'articleTag')
        // .innerJoinAndSelect('followings.follower', 'follower')
        .where('article.id= :id', { id })
      // .orderBy('comment.createTime', 'DESC')
      // .select(['article.id', 'article.title', 'article.content', 'article.category', 'article.author', 'article.introduction', 'article.publish_status', 'article.views', 'article.likes', 'article.collections', 'article.right', 'article.createTime', 'userAccount.avatar', 'userAccount.uuid', 'userAccount.email', 'articleTag', 'beCollected.uuid', 'liker.uuid', 'viewer.uuid', 'follower.uuid',])/* 'author.avatar', 'author.nickname', 'author.uuid', 'comment' */
      const data = await queryBuilder.getOne()
      // const comments = await this.articleComment.find({
      //   where: { article: { id } },
      //   relations: ['userAccount', 'parent', 'replies']
      // })

      // console.log(comments);

      if (data) {
        return {
          code: HttpStatus.OK,
          msg: '成功',
          data,
          // comments:buildCommentTree(comments)
        }
      } else {
        return {
          code: HttpStatus.BAD_GATEWAY,
          msg: '未找到'
        }
      }
    } catch (error) {
      console.log(error);

      return {
        code: HttpStatus.NOT_FOUND,
        msg: '查询失败',
        error
      }
    }


  }
  /** 
    **@description: 通过id更新文章
    **/
  async update(id: number, updateArticleDto: UpdateArticleDto) {
    const statusObj = { 0: '待审核', 1: '待发布', 2: '已发布', 3: '未通过', 4: '草稿箱', 5: '已删除' }
    const article = await this.article.findOne({ where: { id }, relations: ['tags', 'liker', 'beCollected'] })
    if (!article) return { code: HttpStatus.NOT_FOUND, msg: '未找到更新文章' }
    for (let key in updateArticleDto) {
      key !== 'publish_status' && key !== 'tags' && (article[key] = updateArticleDto[key])
    }
    if ('publish_status' in updateArticleDto) {
      article.publish_status = statusObj[updateArticleDto.publish_status]
    }
    //移除先前标签
    if (updateArticleDto.tags && updateArticleDto.tags.length !== 0) {
      article.tags.forEach(async item => {
        await this.articleTag.remove(item)
      })
      let articleTags: Array<ArticleTag> = []
      //循环存储tags
      for (let i = 0; i < updateArticleDto.tags.length; i++) {
        const articleTag = new ArticleTag()
        articleTag.name = updateArticleDto.tags[i]
        await this.articleTag.save(articleTag)
        articleTags.push(articleTag)
      }
      article.tags = articleTags
    }
    try {
      const data = await this.article.save(article)
      return {
        code: HttpStatus.OK,
        msg: `“${data.title}”更新成功`,
        data
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_REQUEST,
        msg: '更新失败',
        data: error
      }
    }
  }
  /** 
    **@description: 删除文章
    **/
  async remove(id: number) {
    const data = await this.article.findOne({ where: { id }, relations: ['tags', 'beCollected', 'liker'] })

    if (!data) return { code: HttpStatus.NOT_FOUND, msg: '未找到文章' }
    try {
      //把关联外键tag删除
      data.tags.forEach(item => {
        this.articleTag.remove(item)
      })
      await this.article.remove(data)
      return {
        data,
        msg: '删除成功',
        code: HttpStatus.OK
      }
    } catch (error) {
      return {
        msg: '删除失败',
        code: HttpStatus.BAD_REQUEST
      }
    }

  }

  /**
  **@description: 查询浏览记录 
  **/
  async findArticleHistory(articleHistoryDto: { uuid: string, keyword?: string, page?: number, pageSize?: number }) {
    const { uuid, keyword, page, pageSize } = articleHistoryDto
    const queryBuilder = this.article.createQueryBuilder('article')
      .leftJoinAndSelect('article.viewer', 'viewer')
      .where('viewer.uuid =:uuid', { uuid })
      .select(['article'])
    if (keyword) {
      queryBuilder.andWhere('article.title LIKE :keyword', { keyword: `%${keyword}%` })
    }
    const total = await queryBuilder.getCount()
    if (page && pageSize) {
      queryBuilder.take(pageSize).skip((page - 1) * pageSize)
    }
    try {
      const data = await queryBuilder.getMany()
      if (!data) return { code: HttpStatus.BAD_REQUEST, msg: '参数错误' }
      return {
        code: HttpStatus.OK,
        msg: '查询成功',
        data,
        total
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_REQUEST,
        msg: '查询失败'
      }
    }

  }


  /**  
    **@description: 文章添加评论
    **/
  async addArticleComment(articleCommentDto: { uuid: string, articleId: number, content: string, parentId?: number }) {
    const { uuid, content, articleId, parentId } = articleCommentDto
    try {
      const userAccount = await this.userAccount.findOne({ where: { uuid }, relations: ['comment'] })
      const article = await this.article.findOne({ where: { id: articleId }, relations: ['comment', 'userAccount'] })
      //判断是否为作者
      if (!userAccount || !article) return { code: HttpStatus.BAD_GATEWAY, msg: '未找到账户/文章' }
      const articleComment = this.articleComment.create({
        author: userAccount.nickname,
        content: content
      })
      if (parentId) {
        const parent = await this.articleComment.findOne({ where: { id: parentId } })
        articleComment.parent = parent

      }
      await this.articleComment.save(articleComment)
      userAccount.comment.push(articleComment)
      article.comment.push(articleComment)
      await Promise.all([
        this.userAccount.save(userAccount),
        this.article.save(article)
      ])
      return {
        code: HttpStatus.OK,
        msg: '评论成功',
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_REQUEST,
        msg: '网络异常'
      }
    }

  }

  /**  
    **@description: 文章删除评论    
    **/
  async delArticleComment(articleCommentDto: { uuid: string, articleId: number, commentId: number }) {
    const { uuid, articleId, commentId } = articleCommentDto
    try {
      const comment = await this.articleComment.createQueryBuilder('articleComment')
        .leftJoinAndSelect("articleComment.userAccount", "userAccount")
        .leftJoinAndSelect("articleComment.article", "article")
        .leftJoinAndSelect('articleComment.replies', 'replies')
        .where("articleComment.id = :commentId", { commentId })
        .andWhere("article.id = :articleId", { articleId })
        .andWhere("userAccount.uuid = :uuid", { uuid })
        .getOne();
      if (!comment) {
        return {
          code: HttpStatus.BAD_REQUEST,
          msg: '未匹配到删除内容'
        }
      }
      await this.articleComment.remove(comment)
      return {
        code: HttpStatus.OK,
        msg: '删除成功',
        data: comment,
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_REQUEST,
        msg: '删除失败'
      }
    }
  }

  /**  
   **@description: 查找文章所有评论+整合  
   **/
  async findArticleComment(articleId: number) {
    // const comments = await this.articleComment.find({
    //   where: { article: { id: articleId } },
    //   relations: ['userAccount', 'parent', 'replies', 'article','likers']
    // })
    const comments = await this.articleComment.createQueryBuilder('articleComment')
      .leftJoinAndSelect('articleComment.userAccount', 'userAccount')
      .leftJoinAndSelect('articleComment.parent', 'parent')
      .leftJoinAndSelect('articleComment.replies', 'replies')
      .leftJoinAndSelect('articleComment.article', 'article')
      .leftJoinAndSelect('articleComment.likers', 'likers')
      .where('article.id=:id', { id: articleId })
      .orderBy('articleComment.createTime', 'DESC')
      .select(['article', 'articleComment', 'userAccount.avatar', 'userAccount.uuid', 'likers', 'replies', 'parent'])
      .getMany()

    const total = comments.length

    return {
      data: buildCommentTree(comments),
      total
    }
  }

  /**  
    **@description: 文章评论点赞   
    **/

  async commentFavor(commentFavorDto: { uuid: string, commentId: number, articleId: number }) {
    const { uuid, commentId, articleId } = commentFavorDto
    try {
      const userAccount = await this.userAccount.findOne({ where: { uuid } })
      const queryBuilder = await this.articleComment.createQueryBuilder('articleComment')
        .leftJoinAndSelect('articleComment.likers', 'userAccount')
        .leftJoinAndSelect('articleComment.article', 'article')
        .where('articleComment.id=:id', { id: commentId })
        .andWhere('article.id=:articleId', { articleId })
        .getOne()

      //查询是否存在点赞
      const hasUserAccount = queryBuilder.likers.findIndex(item => item.uuid == uuid)
      if (hasUserAccount === -1) {
        queryBuilder.likers.push(userAccount)
      } else {
        queryBuilder.likers.splice(hasUserAccount, 1)
      }
      await this.articleComment.save(queryBuilder)

      const hasFavor = hasUserAccount === -1 ? true : false

      return {
        code: HttpStatus.OK,
        msg: hasFavor ? '点赞成功' : '取消点赞',
      }
    } catch (error) {
      return {
        code: HttpStatus.BAD_REQUEST,
        msg: '网络异常'
      }
    }

  }





}